﻿using System;
using System.Windows;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Phone.Tasks;
using RTMBindings;
using RTMBindings.Responses;
using GalaSoft.MvvmLight.Threading;

namespace MilkCart.ViewModel
{
    /// <summary>
    /// ViewModel for the Authentication view
    /// </summary>
    /// @todo Properly check for existing token
    public sealed class AuthenticationViewModel : ViewModel
    {
        public RelayCommand LogonStartCommand { get; private set; }
        public RelayCommand LogonCompleteCommand { get; private set; }

        private bool canStart = true;
        private bool canComplete;

        private RTMFrob frob;
        private RTMUser user;

        public AuthenticationViewModel()
        {
            LogonStartCommand = new RelayCommand(LogonStart, CanStartLogon);
            LogonCompleteCommand = new RelayCommand(LogonComplete, CanCompleteLogon);
            Messenger.Default.Register<NotificationMessage>(this, MessageReceived);
        }

        private void MessageReceived(NotificationMessage msg)
        {
            switch (msg.Notification)
            {
                case NotificationMessages.UpdateMessage:
                    Update();
                    break;
            }
        }

        private void Update()
        {
            if (Token == null)
                return;
            
            RTMAuthBindings.CheckToken(MainPage.ApiKey, MainPage.Secret, Token, ContinueUpdate, ExecutionFailed);
        }

        private void ContinueUpdate(RTMGetTokenResponse response)
        {
            User = response.Auth.User;
            RTMAuthBindings.StoreToken(new RTMToken(response.Auth.Token));
        }

        private void RefreshCommands()
        {
            LogonStartCommand.RaiseCanExecuteChanged();
            LogonCompleteCommand.RaiseCanExecuteChanged();
        }

        public RTMUser User
        {
            get { return user; }
            private set
            {
                user = value;
                DispatcherHelper.CheckBeginInvokeOnUI(() => RaisePropertyChanged("User"));
            }
        }

        private bool CanStartLogon()
        {
            return canStart;
        }

        private bool CanCompleteLogon()
        {
            return canComplete;
        }

        private void CompleteLogonComplete(RTMGetTokenResponse response)
        {
            canStart = true;
            canComplete = false;
            User = response.Auth.User;
            RTMAuthBindings.StoreToken(new RTMToken(response.Auth.Token));

            RefreshCommands();
            var msg = new NotificationMessage(this, NotificationMessages.ClearLastJournalMessage);
            MessengerInstance = Messenger.Default;
            MessengerInstance.Send(msg);
            msg = new NotificationMessage(this, NotificationMessages.UpdateMessage);
            MessengerInstance.Send(msg);
        }

        private void LogonComplete()
        {
            RTMAuthBindings.GetToken(MainPage.ApiKey, MainPage.Secret, frob, CompleteLogonComplete, ExecutionFailed);
            canComplete = false;
            RefreshCommands();
        }

        private void CompleteLogonStart(RTMGetFrobResponse response)
        {
            frob = new RTMFrob(response.Frob);
            var url = RTMAuthBindings.Authenticate(MainPage.ApiKey, MainPage.Secret, frob);

            var task = new WebBrowserTask { Uri = url };
            task.Show();
            canStart = false;
            canComplete = true;
            RefreshCommands();
        }

        private void LogonStart()
        {
            RTMAuthBindings.GetFrob(MainPage.ApiKey, MainPage.Secret, CompleteLogonStart, ExecutionFailed);

            canStart = false;
            canComplete = false;
            RefreshCommands();
        }
    }
}
